﻿// owner 蒋家伟

#include "Application.h"

// std
#include <cassert>

// qt
#include <QFile>

// jsdk
#include "IApplicationEvent.h"
#include "ApplicationEventArgs.h"
#include "Library.h"

using namespace jsdk;

namespace
{
    // 文件锁路径，用来判断是否为单例的
    QString global_lockfilePath = "";

    // 全局App状态

    ApplicationStatus global_ApplicationStatus = ApplicationStatus::BeforeCreate;
}

IApplication * jsdk::Application::create(int & argc, char ** argv)
{
    global_ApplicationStatus = ApplicationStatus::BeforeCreate;
    if (IApplicationEvent* pApplicationEvent = IApplicationEvent::get())
    {
        pApplicationEvent->sendEvent(&ApplicationEventArgs(ApplicationStatus::BeforeCreate));
    }

    static Application s_Application(argc, argv);

    bool success = Library::get().loadLibraries();
    assert(success && "failed to load Libraries!");

    global_ApplicationStatus = ApplicationStatus::AfterCreate;
    if (IApplicationEvent* pApplicationEvent = IApplicationEvent::get())
    {
        pApplicationEvent->sendEvent(&ApplicationEventArgs(ApplicationStatus::AfterCreate));
    }

    return &s_Application;
}

IApplication * jsdk::Application::get()
{
    return s_pApplication;
}

bool jsdk::Application::isRunning()
{
    if (global_lockfilePath.isEmpty())
        return false;
    return QFile::exists(global_lockfilePath);
}

const ApplicationStatus & jsdk::Application::getApplicationStatus()
{
    return global_ApplicationStatus;
}

int jsdk::Application::start() const
{
    global_ApplicationStatus = ApplicationStatus::AfterStart;

    if (IApplicationEvent* pApplicationEvent = IApplicationEvent::get())
    {
        pApplicationEvent->sendEvent(&ApplicationEventArgs(ApplicationStatus::AfterStart));
    }

    QFile file(global_lockfilePath);
    if (file.open(QIODevice::WriteOnly))
    {
        file.close();
    }

    // 如果在之前任意事件中调用了exit() 不再进入循环
    int res = 0;
    if (global_ApplicationStatus != ApplicationStatus::BeforeClose)
    {
        res = m_application.exec();
    }

    // 防止在事件循环中调用exit() 多次触发
    if (global_ApplicationStatus != ApplicationStatus::BeforeClose)
    {
        global_ApplicationStatus = ApplicationStatus::BeforeClose;
        if (IApplicationEvent* pApplicationEvent = IApplicationEvent::get())
        {
            pApplicationEvent->sendEvent(&ApplicationEventArgs(ApplicationStatus::BeforeClose));
        }
    }

    return res;
}

void jsdk::Application::exit()
{
    QApplication::exit(0);
    if (global_ApplicationStatus != ApplicationStatus::BeforeClose)
    {
        global_ApplicationStatus = ApplicationStatus::BeforeClose;
        if (IApplicationEvent* pApplicationEvent = IApplicationEvent::get())
        {
            pApplicationEvent->sendEvent(&ApplicationEventArgs(ApplicationStatus::BeforeClose));
        }
    }
}

std::vector<std::string> jsdk::Application::getCmdParameter() const
{
    std::vector<std::string> res;
    for (auto arg : m_application.arguments())
    {
        res.push_back(arg.toStdString());
    }
    return res;
}

jsdk::Application::Application(int & argc, char ** argv) : m_application(argc, argv)
{
    s_pApplication = this;
    // 生成文件锁
    global_lockfilePath = QCoreApplication::applicationDirPath() + "/file.lf";
}

jsdk::Application::~Application()
{
    s_pApplication = nullptr;
    if (global_lockfilePath.isEmpty())
        return;
    QFile::remove(global_lockfilePath);
}


